use std::collections::HashMap;
use std::sync::OnceLock;

static MAPS: OnceLock<(
    (HashMap<char, char>, HashMap<String, String>), // s2t: (chars, phrases)
    (HashMap<char, char>, HashMap<String, String>), // t2s: (chars, phrases)
    HashMap<char, char>,                            // tw_variants
)> = OnceLock::new();

pub fn converter(input: &str, tp: &str) -> String {
    let parts: Vec<&str> = input.trim_end_matches(',').split(',').collect();
    if parts.is_empty() {
        return String::new();
    }

    let text = parts[0];
    let mode = tp.trim_end_matches(',');

    let ((s2t_chars, s2t_phrases), (t2s_chars, t2s_phrases), tw_variants) =
        MAPS.get_or_init(|| init_maps());

    let (char_map, phrase_map) = match mode {
        "s2t" => (s2t_chars, s2t_phrases),
        "t2s" => (t2s_chars, t2s_phrases),
        _ => return String::new(),
    };

    let mut result = String::new();
    let mut i = 0;
    let chars: Vec<char> = text.chars().collect();

    while i < chars.len() {
        let mut matched = false;

        for len in (2..=4).rev() {
            if i + len <= chars.len() {
                let phrase: String = chars[i..i + len].iter().collect();
                if let Some(converted) = phrase_map.get(&phrase) {
                    if mode == "s2t" {
                        for c in converted.chars() {
                            result.push(tw_variants.get(&c).copied().unwrap_or(c));
                        }
                    } else {
                        result.push_str(converted);
                    }
                    i += len;
                    matched = true;
                    break;
                }
            }
        }

        if !matched {
            let converted = char_map.get(&chars[i]).copied().unwrap_or(chars[i]);
            if mode == "s2t" {
                result.push(tw_variants.get(&converted).copied().unwrap_or(converted));
            } else {
                result.push(converted);
            }
            i += 1;
        }
    }

    result
}

fn init_maps() -> (
    (HashMap<char, char>, HashMap<String, String>),
    (HashMap<char, char>, HashMap<String, String>),
    HashMap<char, char>,
) {
    let mut s2t_chars = HashMap::new();
    let t2s_chars = HashMap::new();
    let mut s2t_phrases = HashMap::new();
    let mut t2s_phrases = HashMap::new();
    let mut tw_variants = HashMap::new();

    if let Ok(content) = std::fs::read_to_string("src/STCharacters.txt") {
        for line in content.lines() {
            let parts: Vec<&str> = line.split_whitespace().collect();
            if parts.len() >= 2 {
                if let (Some(s), Some(t)) = (parts[0].chars().next(), parts[1].chars().next()) {
                    s2t_chars.insert(s, t);
                }
            }
        }
    }

    if let Ok(content) = std::fs::read_to_string("src/TWVariants.txt") {
        for line in content.lines() {
            let parts: Vec<&str> = line.split_whitespace().collect();
            if parts.len() >= 2 {
                if let (Some(orig), Some(tw)) = (parts[0].chars().next(), parts[1].chars().next()) {
                    tw_variants.insert(orig, tw);
                }
            }
        }
    }

    if let Ok(content) = std::fs::read_to_string("src/STPhrases.txt") {
        for line in content.lines() {
            let parts: Vec<&str> = line.split_whitespace().collect();
            if parts.len() >= 2 {
                s2t_phrases.insert(parts[0].to_string(), parts[1].to_string());
            }
        }
    }

    if let Ok(content) = std::fs::read_to_string("src/TSPhrases.txt") {
        for line in content.lines() {
            let parts: Vec<&str> = line.split_whitespace().collect();
            if parts.len() >= 2 {
                t2s_phrases.insert(parts[0].to_string(), parts[1].to_string());
            }
        }
    }

    (
        (s2t_chars, s2t_phrases),
        (t2s_chars, t2s_phrases),
        tw_variants,
    )
}
